package it.ctr.game.toolkit;

import it.ctr.game.toolkit.BrickBox;

import java.awt.*;
import java.util.Random;
import com.mojang.mario.level.*;


public class LevelRenderer
{
    private int xCam;
    private int yCam;
    private int nLayer;
    private Image[] image = new Image[3];
    private Graphics2D[] g = new Graphics2D[3];
    private static final Color transparent = new Color(0, 0, 0, 0);
    private Level level;

    public int width;
    public int height;

    public LevelRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height)
    {
        this.width = width;
        this.height = height;
        this.level = level;
        for (int i = 0; i < 3; i++) {
            image[i] = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK);
            g[i] = (Graphics2D) image[i].getGraphics();
            g[i].setComposite(AlphaComposite.Src);	
		}
    }

    public void setCam(int xCam, int yCam)
    {
        int xCamD = this.xCam - xCam;
        int yCamD = this.yCam - yCam;
        this.xCam = xCam;
        this.yCam = yCam;

        for (int i = 0; i < 3; i++) {
             g[i].setComposite(AlphaComposite.Src);
            g[i].copyArea(0, 0, width, height, xCamD, yCamD);
		}

        if (xCamD < 0)
        {
            if (xCamD < -width) xCamD = -width;
            updateArea(width + xCamD, 0, -xCamD, height);
        }
        else if (xCamD > 0)
        {
            if (xCamD > width) xCamD = width;
            updateArea(0, 0, xCamD, height);
        }

        if (yCamD < 0)
        {
            if (yCamD < -width) yCamD = -width;
            updateArea(0, height + yCamD, width, -yCamD);
        }
        else if (yCamD > 0)
        {
            if (yCamD > width) yCamD = width;
            updateArea(0, 0, width, yCamD);
        }
    }

    private void updateArea(int x0, int y0, int w, int h)
    {
        for (int i = 0; i < 3; i++) {
            g[i].setBackground(transparent);
           g[i].clearRect(x0, y0, w, h);
		}
         
        int xTileStart = (x0 + xCam) / Level.BLOCK_SIZE;
        int yTileStart = (y0 + yCam) / Level.BLOCK_SIZE;
        int xTileEnd = (x0 + xCam + w) / Level.BLOCK_SIZE;
        int yTileEnd = (y0 + yCam + h) / Level.BLOCK_SIZE;
        int b;
        for (int x = xTileStart; x <= xTileEnd; x++)
        {
            for (int y = yTileStart; y <= yTileEnd; y++)
            {
               	if (nLayer == -1) {
                    for (int i = 0; i < Level.NUM_LAYER; i++) {
                    	b = level.getByteLayer(x, y, i) & 0xff; 
                        g[i].drawImage(BrickBox.levelBrick[b % 16][b / 16], (x * Level.BLOCK_SIZE) - xCam, (y * Level.BLOCK_SIZE) - yCam, null);       
            		}
            	} else {
            		b = level.getByteLayer(x, y, nLayer) & 0xff; 
                    g[nLayer].drawImage(BrickBox.levelBrick[b % 16][b / 16], (x * Level.BLOCK_SIZE) - xCam, (y * Level.BLOCK_SIZE) - yCam, null);       
            	}
            	
            }
        }
    }

    public void render(Graphics g, int tick, float alpha)
    {
    	   for (int i = 0; i < Level.NUM_LAYER; i++) {
    		   g.drawImage(image[i], 0, 0, null);
    	}


//        for (int x = xCam / Level.BLOCK_SIZE; x <= (xCam + width) / Level.BLOCK_SIZE; x++)
//            for (int y = yCam / Level.BLOCK_SIZE; y <= (yCam + height) / Level.BLOCK_SIZE; y++)
//            {
//                byte b = level.getBlock(x, y);
//
//                int animTime = 0;
////                
//                    int animTime = (tick / 3) % 4;
//
//                    if ((b % Level.BLOCK_SIZE) / 4 == 0 && b / Level.BLOCK_SIZE == 1)
//                    {
//                        animTime = (tick / 2 + (x + y) / 8) % 20;
//                        if (animTime > 3) animTime = 0;
//                    }
//                    if ((b % Level.BLOCK_SIZE) / 4 == 3 && b / Level.BLOCK_SIZE == 0)
//                    {
//                        animTime = 2;
//                    }
//                    int yo = 0;
//                    if (x >= 0 && y >= 0 && x < level.width && y < level.height) yo = level.layer1[x][y];
//                    if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
//                    //g.drawImage(BrickBox.levelBrick[((b % (Level.BLOCK_SIZE*4))/Level.BLOCK_SIZE)][b / (Level.BLOCK_SIZE*4)], (x * Level.BLOCK_SIZE) - xCam, (y * Level.BLOCK_SIZE) - yCam - yo, null);
                
                   
                    
                    //g.drawImage(BrickBox.levelBrick[b % Level.BLOCK_SIZE][b / Level.BLOCK_SIZE], (x * Level.BLOCK_SIZE) - xCam, (y * Level.BLOCK_SIZE) - yCam, null);
            
                /*                else if (b == Level.TILE_BONUS)
                 {
                 int animTime = (tick / 3) % 4;
                 int yo = 0;
                 if (x >= 0 && y >= 0 && x < level.width && y < level.height) yo = level.data[x][y];
                 if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
                 g.drawImage(Art.mapSprites[(4 + animTime)][0], (x << 4) - xCam, (y << 4) - yCam - yo, null);
                 }*/

             
            //}
    }

    public void repaint(int x, int y, int w, int h)
    {
        updateArea(x * Level.BLOCK_SIZE - xCam, y * Level.BLOCK_SIZE - yCam, w * Level.BLOCK_SIZE, h * Level.BLOCK_SIZE);
    }

    public void setLevel(Level level)
    {
        this.level = level;
        updateArea(0, 0, width, height);
    }

    public void renderExit0(Graphics g, int tick, float alpha, boolean bar)
    {
        for (int y = level.yExit; y < level.yExit+8; y++)
        {
            g.drawImage(BrickBox.level[12][y == level.yExit + 8 ? 4 : 5], (level.xExit*Level.BLOCK_SIZE) - xCam - 16, (y*Level.BLOCK_SIZE) - yCam, null);
        }
        int yh = level.yExit * 16 - (int) ((Math.sin((tick + alpha) / 20) * 0.5 + 0.5) * 7 * 16) - 8;
        if (bar)
        {
            g.drawImage(BrickBox.level[12][3], (level.xExit*Level.BLOCK_SIZE) - xCam - 16, yh*Level.BLOCK_SIZE - yCam, null);
            g.drawImage(BrickBox.level[13][3], (level.xExit*Level.BLOCK_SIZE) - xCam, yh*Level.BLOCK_SIZE - yCam, null);
        }
    }


    public void renderExit1(Graphics g, int tick, float alpha)
    {
        for (int y = level.yExit; y < level.yExit+8; y++)
        {
            g.drawImage(BrickBox.level[13][y == level.yExit + 8 ? 4 : 5], (level.xExit*Level.BLOCK_SIZE) - xCam + 16, (y*Level.BLOCK_SIZE) - yCam, null);
        }
    }

	public void setLayer(int layer) {
		nLayer = layer;
	}

	public int getLayer() {
		return nLayer;
	}
}